package com.supplychain.scm.core.common.exception;

import lombok.SneakyThrows;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName CustomAssert
 * @Description 自定义断言
 * @createTime 16:27:00 2022/12/03
 */
public class CustomAssert {

    private static int DEFAULT_CODE = 500;
    private static Class<? extends CustomException> clazz;

    public static void setClazz(Class<? extends CustomException> clazz) {
        CustomAssert.clazz = clazz;
    }

    public static void state(boolean expression, IException exception) {
        if (!expression) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void state(boolean expression, IException exception,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void state(boolean expression, IException exception,Object data) {
        if (!expression) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void state(boolean expression, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void state(boolean expression, String message) {
        if (!expression) {
            failMethod(message);
        }
    }

    public static void state(boolean expression, String message,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(message,exceptionClass);
        }
    }

    public static void state(boolean expression, String message,Object data) {
        if (!expression) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void state(boolean expression, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void state(boolean expression,int code, String message) {
        if (!expression) {
            failMethod(code,message);
        }
    }

    public static void state(boolean expression,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void state(boolean expression,int code, String message,Object data) {
        if (!expression) {
            failMethod(code,message,data);
        }
    }

    public static void state(boolean expression,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void state(boolean expression, Supplier<String> messageSupplier) {
        if (!expression) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void state(boolean expression, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void state(boolean expression, Supplier<String> messageSupplier,Object data) {
        if (!expression) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void state(boolean expression, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void isTrue(boolean expression, IException exception) {
        if (!expression) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void isTrue(boolean expression, IException exception,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void isTrue(boolean expression, IException exception,Object data) {
        if (!expression) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void isTrue(boolean expression, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void isTrue(boolean expression, String message) {
        if (!expression) {
            failMethod(message);
        }
    }

    public static void isTrue(boolean expression, String message,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(message,exceptionClass);
        }
    }

    public static void isTrue(boolean expression, String message,Object data) {
        if (!expression) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void isTrue(boolean expression, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void isTrue(boolean expression,int code, String message) {
        if (!expression) {
            failMethod(code,message);
        }
    }

    public static void isTrue(boolean expression,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void isTrue(boolean expression,int code, String message,Object data) {
        if (!expression) {
            failMethod(code,message,data);
        }
    }

    public static void isTrue(boolean expression,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void isTrue(boolean expression, Supplier<String> messageSupplier) {
        if (!expression) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void isTrue(boolean expression, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void isTrue(boolean expression, Supplier<String> messageSupplier,Object data) {
        if (!expression) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void isTrue(boolean expression, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (!expression) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object, IException exception) {
        if (object != null) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void isNull(@Nullable Object object, IException exception,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object, IException exception,Object data) {
        if (object != null) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void isNull(@Nullable Object object, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object, String message) {
        if (object != null) {
            failMethod(message);
        }
    }

    public static void isNull(@Nullable Object object, String message,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(message,exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object, String message,Object data) {
        if (object != null) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void isNull(@Nullable Object object, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object,int code, String message) {
        if (object != null) {
            failMethod(code,message);
        }
    }

    public static void isNull(@Nullable Object object,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object,int code, String message,Object data) {
        if (object != null) {
            failMethod(code,message,data);
        }
    }

    public static void isNull(@Nullable Object object,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object, Supplier<String> messageSupplier) {
        if (object != null) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void isNull(@Nullable Object object, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void isNull(@Nullable Object object, Supplier<String> messageSupplier,Object data) {
        if (object != null) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void isNull(@Nullable Object object, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (object != null) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object, IException exception) {
        if (object == null) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void notNull(@Nullable Object object, IException exception,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object, IException exception,Object data) {
        if (object == null) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void notNull(@Nullable Object object, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object, String message) {
        if (object == null) {
            failMethod(message);
        }
    }

    public static void notNull(@Nullable Object object, String message,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(message,exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object, String message,Object data) {
        if (object == null) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void notNull(@Nullable Object object, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object,int code, String message) {
        if (object == null) {
            failMethod(code,message);
        }
    }

    public static void notNull(@Nullable Object object,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object,int code, String message,Object data) {
        if (object == null) {
            failMethod(code,message,data);
        }
    }

    public static void notNull(@Nullable Object object,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(code,message,data,exceptionClass);
        }
    }


    public static void notNull(@Nullable Object object, Supplier<String> messageSupplier) {
        if (object == null) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void notNull(@Nullable Object object, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void notNull(@Nullable Object object, Supplier<String> messageSupplier,Object data) {
        if (object == null) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void notNull(@Nullable Object object, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (object == null) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text, IException exception) {
        if (!StringUtils.hasLength(text)) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void hasLength(@Nullable String text, IException exception,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text, IException exception,Object data) {
        if (!StringUtils.hasLength(text)) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void hasLength(@Nullable String text, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text, String message) {
        if (!StringUtils.hasLength(text)) {
            failMethod(message);
        }
    }

    public static void hasLength(@Nullable String text, String message,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(message,exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text, String message,Object data) {
        if (!StringUtils.hasLength(text)) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void hasLength(@Nullable String text, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text,int code, String message) {
        if (!StringUtils.hasLength(text)) {
            failMethod(code,message);
        }
    }

    public static void hasLength(@Nullable String text,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text,int code, String message,Object data) {
        if (!StringUtils.hasLength(text)) {
            failMethod(code,message,data);
        }
    }

    public static void hasLength(@Nullable String text,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text, Supplier<String> messageSupplier) {
        if (!StringUtils.hasLength(text)) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void hasLength(@Nullable String text, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void hasLength(@Nullable String text, Supplier<String> messageSupplier,Object data) {
        if (!StringUtils.hasLength(text)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void hasLength(@Nullable String text, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasLength(text)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void hasText(@Nullable String text, IException exception) {
        if (!StringUtils.hasText(text)) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void hasText(@Nullable String text, IException exception,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void hasText(@Nullable String text, IException exception,Object data) {
        if (!StringUtils.hasText(text)) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void hasText(@Nullable String text, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void hasText(@Nullable String text, String message) {
        if (!StringUtils.hasText(text)) {
            failMethod(message);
        }
    }

    public static void hasText(@Nullable String text, String message,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(message,exceptionClass);
        }
    }

    public static void hasText(@Nullable String text, String message,Object data) {
        if (!StringUtils.hasText(text)) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void hasText(@Nullable String text, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void hasText(@Nullable String text,int code, String message) {
        if (!StringUtils.hasText(text)) {
            failMethod(code,message);
        }
    }

    public static void hasText(@Nullable String text,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void hasText(@Nullable String text,int code, String message,Object data) {
        if (!StringUtils.hasText(text)) {
            failMethod(code,message,data);
        }
    }

    public static void hasText(@Nullable String text,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void hasText(@Nullable String text, Supplier<String> messageSupplier) {
        if (!StringUtils.hasText(text)) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void hasText(@Nullable String text, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void hasText(@Nullable String text, Supplier<String> messageSupplier,Object data) {
        if (!StringUtils.hasText(text)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void hasText(@Nullable String text, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (!StringUtils.hasText(text)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, IException exception) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, IException exception,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, IException exception,Object data) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(exception.code(),exception.message(),data);
        }
    }


    public static void doesNotContain(@Nullable String textToSearch, String substring, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, String message) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(message);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, String message,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(message,exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, String message,Object data) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring,int code, String message) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(code,message);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring,int code, String message,Object data) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(code,message,data);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, Supplier<String> messageSupplier) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, Supplier<String> messageSupplier,Object data) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void doesNotContain(@Nullable String textToSearch, String substring, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (StringUtils.hasLength(textToSearch) && StringUtils.hasLength(substring) &&
                textToSearch.contains(substring)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array, IException exception) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void notEmpty(@Nullable Object[] array, IException exception,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array, IException exception,Object data) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void notEmpty(@Nullable Object[] array, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array, String message) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(message);
        }
    }

    public static void notEmpty(@Nullable Object[] array, String message,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(message,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array, String message,Object data) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void notEmpty(@Nullable Object[] array, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array,int code, String message) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(code,message);
        }
    }

    public static void notEmpty(@Nullable Object[] array,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(code,message,exceptionClass);
        }
    }


    public static void notEmpty(@Nullable Object[] array,int code, String message,Object data) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(code,message,data);
        }
    }

    public static void notEmpty(@Nullable Object[] array,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array, Supplier<String> messageSupplier) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void notEmpty(@Nullable Object[] array, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Object[] array, Supplier<String> messageSupplier,Object data) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void notEmpty(@Nullable Object[] array, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (ObjectUtils.isEmpty(array)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void noNullElements(@Nullable Object[] array, IException exception) {
        if (array != null) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(exception.code(),exception.message());
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, IException exception,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(exception.code(),exception.message(),exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, IException exception,Object data) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(exception.code(),exception.message(),data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(exception.code(),exception.message(),data,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, String message) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(message);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, String message,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(message,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, String message,Object data) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,message,data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,message,data,exceptionClass);
                }
            }
        }
    }


    public static void noNullElements(@Nullable Object[] array,int code, String message) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(code,message);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(code,message,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array,int code, String message,Object data) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(code,message,data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(code,message,data,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, Supplier<String> messageSupplier) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(nullSafeGet(messageSupplier));
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(nullSafeGet(messageSupplier),exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, Supplier<String> messageSupplier,Object data) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Object[] array, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (Objects.nonNull(array)) {
            for (Object element : array) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
                }
            }
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, IException exception) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, IException exception,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, IException exception,Object data) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, String message) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(message);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, String message,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(message,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, String message,Object data) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection,int code, String message) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(code,message);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection,int code, String message,Object data) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(code,message,data);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, Supplier<String> messageSupplier) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, Supplier<String> messageSupplier,Object data) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void notEmpty(@Nullable Collection<?> collection, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(collection)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, IException exception) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(exception.code(),exception.message());
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, IException exception,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(exception.code(),exception.message(),exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, IException exception,Object data) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(exception.code(),exception.message(),data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(exception.code(),exception.message(),data,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, String message) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(message);
                }
            }
        }
    }


    public static void noNullElements(@Nullable Collection<?> collection, String message,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(message,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, String message,Object data) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,message,data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,message,data,exceptionClass);
                }
            }
        }
    }


    public static void noNullElements(@Nullable Collection<?> collection,int code, String message) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(code,message);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(code,message,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection,int code, String message,Object data) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(code,message,data);
                }
            }
        }
    }


    public static void noNullElements(@Nullable Collection<?> collection,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(code,message,data,exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, Supplier<String> messageSupplier) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(nullSafeGet(messageSupplier));
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(nullSafeGet(messageSupplier),exceptionClass);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, Supplier<String> messageSupplier,Object data) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
                }
            }
        }
    }

    public static void noNullElements(@Nullable Collection<?> collection, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (collection != null) {
            for (Object element : collection) {
                if (element == null) {
                    failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
                }
            }
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, IException exception) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(exception.code(),exception.message());
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, IException exception,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(exception.code(),exception.message(),exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, IException exception,Object data) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(exception.code(),exception.message(),data);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, String message) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(message);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, String message,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(message,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, String message,Object data) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(DEFAULT_CODE,message,data);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(DEFAULT_CODE,message,data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map,int code, String message) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(code,message);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map,int code, String message,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(code,message,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map,int code, String message,Object data) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(code,message,data);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(code,message,data,exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, Supplier<String> messageSupplier) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(nullSafeGet(messageSupplier));
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(nullSafeGet(messageSupplier),exceptionClass);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, Supplier<String> messageSupplier,Object data) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data);
        }
    }

    public static void notEmpty(@Nullable Map<?, ?> map, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        if (CollectionUtils.isEmpty(map)) {
            failMethod(DEFAULT_CODE,nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, String message) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, message,null,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, String message,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, message,null,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, String message,Object data) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, message,data,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, String message,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, message,data,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,int code, String message) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,code, message,null,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,int code, String message,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,code, message,null,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,int code, String message,Object data) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,code, message,data,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,code, message,data,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,IException exception) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,exception.code(),exception.message(),null,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,IException exception,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,exception.code(),exception.message(),null,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,IException exception,Object data) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,exception.code(),exception.message(),data,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,exception.code(),exception.message(),data,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, Supplier<String> messageSupplier) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, nullSafeGet(messageSupplier),null,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, nullSafeGet(messageSupplier),null,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, Supplier<String> messageSupplier,Object data) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, nullSafeGet(messageSupplier),data,null);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(type, "Type to check against must not be null");
        if (!type.isInstance(obj)) {
            instanceCheckFailed(type, obj,null, nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj) {
        isInstanceOf(type, obj, "");
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,Class<? extends CustomException> exceptionClass) {
        isInstanceOf(type, obj, "",exceptionClass);
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,Object data) {
        isInstanceOf(type, obj,DEFAULT_CODE, "",data);
    }

    public static void isInstanceOf(Class<?> type, @Nullable Object obj,Object data,Class<? extends CustomException> exceptionClass) {
        isInstanceOf(type, obj,DEFAULT_CODE, "",data,exceptionClass);
    }


    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, String message) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, message,null,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, String message,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, message,null,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, String message,Object data) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, message,data,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, String message,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, message,data,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,int code, String message) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,code, message,null,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,int code, String message,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,code, message,null,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,int code, String message,Object data) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,code, message,data,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,int code, String message,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,code, message,data,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,IException exception) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,exception.code(), exception.message(),null,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,IException exception,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,exception.code(), exception.message(),null,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,IException exception,Object data) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,exception.code(), exception.message(),data,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType,IException exception,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,exception.code(), exception.message(),data,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, Supplier<String> messageSupplier) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, nullSafeGet(messageSupplier),null,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, Supplier<String> messageSupplier,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, nullSafeGet(messageSupplier),null,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, Supplier<String> messageSupplier,Object data) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, nullSafeGet(messageSupplier),data,null);
        }
    }

    public static void isAssignable(Class<?> superType, @Nullable Class<?> subType, Supplier<String> messageSupplier,Object data,Class<? extends CustomException> exceptionClass) {
        notNull(superType, "Super type to check against must not be null");
        if (subType == null || !superType.isAssignableFrom(subType)) {
            assignableCheckFailed(superType, subType,null, nullSafeGet(messageSupplier),data,exceptionClass);
        }
    }

    public static void isAssignable(Class<?> superType, Class<?> subType) {
        isAssignable(superType, subType, "");
    }

    public static void isAssignable(Class<?> superType, Class<?> subType,Class<? extends CustomException> exceptionClass) {
        isAssignable(superType, subType ,"",null,exceptionClass);
    }

    public static void isAssignable(Class<?> superType, Class<?> subType,Object data) {
        isAssignable(superType, subType, "",data);
    }

    public static void isAssignable(Class<?> superType, Class<?> subType,Object data,Class<? extends CustomException> exceptionClass) {
        isAssignable(superType, subType, "",data,exceptionClass);
    }

    private static void instanceCheckFailed(Class<?> type, @Nullable Object obj,Integer code, @Nullable String msg,Object data,Class<? extends CustomException> exceptionClass) {
        String className = (obj != null ? obj.getClass().getName() : "null");
        String result = "";
        boolean defaultMessage = true;
        if (StringUtils.hasLength(msg)) {
            if (endsWithSeparator(msg)) {
                result = msg + " ";
            }
            else {
                result = messageWithTypeName(msg, className);
                defaultMessage = false;
            }
        }
        if (defaultMessage) {
            result = result + ("Object of class [" + className + "] must be an instance of " + type);
        }
        code = Objects.isNull(code) ? DEFAULT_CODE : code;
        if(Objects.isNull(data)) {
            if(Objects.isNull(exceptionClass)) {
                failMethod(code,result);
            } else {
                failMethod(code,result,exceptionClass);
            }
        }else{
            if(Objects.isNull(exceptionClass)) {
                failMethod(code,result,data);
            } else {
                failMethod(code,result,data,exceptionClass);
            }
        }
    }

    private static void assignableCheckFailed(Class<?> superType, @Nullable Class<?> subType,Integer code, @Nullable String msg,Object data,Class<? extends CustomException> exceptionClass) {
        String result = "";
        boolean defaultMessage = true;
        if (StringUtils.hasLength(msg)) {
            if (endsWithSeparator(msg)) {
                result = msg + " ";
            }
            else {
                result = messageWithTypeName(msg, subType);
                defaultMessage = false;
            }
        }
        if (defaultMessage) {
            result = result + (subType + " is not assignable to " + superType);
        }
        code = Objects.isNull(code) ? DEFAULT_CODE : code;
        if(Objects.isNull(data)) {
            if(Objects.isNull(exceptionClass)) {
                failMethod(code,result);
            } else {
                failMethod(code,result,exceptionClass);
            }
        } else {
            if(Objects.isNull(exceptionClass)) {
                failMethod(code,result,data);
            } else {
                failMethod(code,result,data,exceptionClass);
            }
        }
    }

    private static boolean endsWithSeparator(String msg) {
        return (msg.endsWith(":") || msg.endsWith(";") || msg.endsWith(",") || msg.endsWith("."));
    }

    private static String messageWithTypeName(String msg, @Nullable Object typeName) {
        return msg + (msg.endsWith(" ") ? "" : ": ") + typeName;
    }


    @Nullable
    private static String nullSafeGet(@Nullable Supplier<String> messageSupplier) {
        return (messageSupplier != null ? messageSupplier.get() : null);
    }

    @SneakyThrows
    private static void failMethod(String message){
        if(Objects.isNull(clazz)){
            setClazz(CustomException.class);
        }
        try {
            Method method = clazz.getMethod("fail", String.class);
            method.invoke(null, message);
        }catch (NoSuchMethodException e){
            throw new RuntimeException(e);
        }catch (Exception e){
            throw Objects.nonNull(e.getCause()) ? e.getCause() : e;
        }
    }

    @SneakyThrows
    private static void failMethod(int code, String message){
        if(Objects.isNull(clazz)){
            setClazz(CustomException.class);
        }
        Method method = null;
        try {
            method = clazz.getMethod("fail",int.class, String.class);
            method.invoke(null, code, message);
        }catch (NoSuchMethodException e){
            throw new RuntimeException(e);
        }catch (Exception e){
            throw Objects.nonNull(e.getCause()) ? e.getCause() : e;
        }
    }

    @SneakyThrows
    private static void failMethod(int code,String message,Object data){
        if(Objects.isNull(clazz)){
            setClazz(CustomException.class);
        }
        try {
            Method method = clazz.getMethod("fail",int.class, String.class,Object.class);
            method.invoke(null,code,message,data);
        }catch (NoSuchMethodException e){
            throw new RuntimeException(e);
        }catch (Exception e){
            throw Objects.nonNull(e.getCause()) ? e.getCause() : e;
        }
    }

    @SneakyThrows
    private static void failMethod(String message,Class<? extends CustomException> exceptionClass){
        if(Objects.isNull(exceptionClass)){
            exceptionClass = CustomException.class;
        }
        try{
            Method method = exceptionClass.getMethod("fail", String.class);
            method.invoke(null,message);
        }catch (NoSuchMethodException e){
            throw new RuntimeException(e);
        }catch (Exception e){
            throw Objects.nonNull(e.getCause()) ? e.getCause() : e;
        }
    }

    @SneakyThrows
    private static void failMethod(int code,String message,Class<? extends CustomException> exceptionClass){
        if(Objects.isNull(exceptionClass)){
            exceptionClass = CustomException.class;
        }
        try{
            Method method = exceptionClass.getMethod("fail",int.class, String.class);
            method.invoke(null,code,message);
        }catch (NoSuchMethodException e){
            throw new RuntimeException(e);
        }catch (Exception e){
            throw Objects.nonNull(e.getCause()) ? e.getCause() : e;
        }
    }

    @SneakyThrows
    private static void failMethod(int code,String message,Object data,Class<? extends CustomException> exceptionClass){
        if(Objects.isNull(exceptionClass)){
            exceptionClass = CustomException.class;
        }
        try{
            Method method = exceptionClass.getMethod("fail",int.class, String.class,Object.class);
            method.invoke(null,code,message,data);
        }catch (NoSuchMethodException e){
            throw new RuntimeException(e);
        }catch (Exception e){
            throw Objects.nonNull(e.getCause()) ? e.getCause() : e;
        }
    }
}
